﻿using Dotnet.Utils.Utility.CollectionUtil;
using System;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Dotnet.Utils.Utility.Serialize
{
    public static class DeserializeExtensions
    {
        public static T Deserialize<T>(this string json) => JsonSerializer.Deserialize<T>(json)!;

        public static string Serialize(this object obj)
        {
            var defaultSerializerSettings = new JsonSerializerOptions
            {
                // 整齐打印
                WriteIndented = true,
                // 关闭转义，默认情况下，序列化程序会转义所有非 ASCII 字符。 即，会将中文替换为 \uxxxx，其中 xxxx 为字符的 Unicode 代码。
                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
                // 反序列化不区分大小写
                PropertyNameCaseInsensitive = true,
                // 驼峰命名
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                // 对字典的键进行驼峰命名
                DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
                // 序列化的时候忽略null值属性
                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
                // 忽略只读属性，因为只读属性只能序列化而不能反序列化，所以在以json为储存数据的介质的时候，序列化只读属性意义不大
                IgnoreReadOnlyFields = true,
                // 不允许结尾有逗号的不标准json
                AllowTrailingCommas = false,
                // 不允许有注释的不标准json
                ReadCommentHandling = JsonCommentHandling.Disallow,
                // 允许在反序列化的时候原本应为数字的字符串（带引号的数字）转为数字
                NumberHandling = JsonNumberHandling.AllowReadingFromString,
                // 处理循环引用类型
                ReferenceHandler = ReferenceHandler.IgnoreCycles,
            };
            return JsonSerializer.Serialize(obj, defaultSerializerSettings);
        }

        public static JsonSerializerOptions Create(JsonSerializerOptions baseOptions, JsonConverter removeConverter, params JsonConverter[] addConverters)
        {
            return Create(baseOptions, x => x == removeConverter, addConverters);
        }

        public static JsonSerializerOptions Create(JsonSerializerOptions baseOptions, Func<JsonConverter, bool> removeConverterPredicate, params JsonConverter[] addConverters)
        {
            var options = new JsonSerializerOptions(baseOptions);
            options.Converters.RemoveAll(removeConverterPredicate);
            options.Converters.AddIfNotContains(addConverters);
            return options;
        }
    }
}